package com.tduck.cloud.dashboard.service.charts;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.map.MapUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.tduck.cloud.dashboard.request.ChartDataRequest;
import com.tduck.cloud.dashboard.vo.DatasetVO;
import com.tduck.cloud.dashboard.vo.GroupQueryResult;
import com.tduck.cloud.report.data.params.GroupQueryParams;
import com.tduck.cloud.report.data.template.DataSearchTemplate;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.tduck.cloud.report.data.template.MongoDataSearchTemplateImpl.MONGODB_ID;


/**
 * 基础图标数据服务
 *
 * @author tduck
 */
public abstract class BaseDashboardChartDataService {


    @Autowired
    protected DataSearchTemplate dataSearchTemplate;


    protected static final String DATA_ID = "_id";

    /**
     * 获取图表数据
     *
     * @param request 请求
     * @return 图标所需数据格式
     */
    public abstract Map<String, Object> getChartData(ChartDataRequest request);


    /**
     * 默认echarts数据
     *
     * @param request 请求参数
     */
    protected Map<String, Object> getDataset(ChartDataRequest request) {
        if (CollUtil.isEmpty(request.getDimension())) {
            return BeanUtil.beanToMap(new DatasetVO());
        }
        List<Map> mappedResults = this.getGroupQueryDataList(request);
        if (CollUtil.isEmpty(mappedResults)) {
            return BeanUtil.beanToMap(new DatasetVO());
        }
        //  // 完成映射，参见后文。
        //    dimensions: ['product', '2015', '2016', '2017'],
        //    source: [
        //      { product: 'Matcha Latte', '2015': 43.3, '2016': 85.8, '2017': 93.7 },
        //      { product: 'Milk Tea', '2015': 83.1, '2016': 73.4, '2017': 55.1 },
        //      { product: 'Cheese Cocoa', '2015': 86.4, '2016': 65.2, '2017': 82.5 },
        //      { product: 'Walnut Brownie', '2015': 72.4, '2016': 53.9, '2017': 39.1 }
        //    ]
        //  },
        List<String> dimensions = Lists.newArrayList(DATA_ID);
        Map<String, String> dimensionMap = request.getIndex().stream().collect(Collectors.toMap(item -> item.getId() + "_" + item.getAggregateType(), ChartDataRequest.IndexField::getLabel, (value1, value2) -> value2));
        dimensions.addAll(dimensionMap.values());
        List<Object> source = Lists.newArrayList();
        for (Map<String, Object> map : mappedResults) {
            Map<String, Object> sourceMap = Maps.newHashMap();
            for (String key : map.keySet()) {
                Object o = map.get(key);
                if (o instanceof Map) {
                    Map<String, Object> valueMap = (Map<String, Object>) o;
                    sourceMap.put(dimensionMap.getOrDefault(key, key), CollUtil.join(valueMap.values(), ","));
                } else {
                    sourceMap.put(dimensionMap.getOrDefault(key, key), map.get(key));
                }
            }
            source.add(sourceMap);
        }
        return BeanUtil.beanToMap(new DatasetVO(dimensions, source));
    }

    /**
     * 查询数据
     *
     * @param request 参数
     */
    protected List<Map> getGroupQueryDataList(ChartDataRequest request) {
        List<GroupQueryParams.GroupField> groupFieldList = request.getDimension().stream().map(item -> new GroupQueryParams.GroupField(item.getId(), null != item.getDateFormat() ? item.getDateFormat().getFormat() : "")).collect(Collectors.toList());
        List<GroupQueryParams.AggregateField> fieldList = request.getIndex().stream().map(item -> new GroupQueryParams.AggregateField(item.getId(), item.getAggregateType())).collect(Collectors.toList());
        GroupQueryParams params = new GroupQueryParams();
        params.setGroupByFields(groupFieldList);
        params.setFilter(Lists.newArrayList(request.getFilter(), request.getLinkageFilter()));
        params.setAggregateFields(fieldList);
        params.setQueryObjName(request.getIndexName());
        params.setLimit(request.getLimit());
        params.setSortFields(request.getSorts());
        return dataSearchTemplate.groupQuery(params);
    }


    /**
     * 查询数据
     *
     * @param request 参数
     */
    protected GroupQueryResult getGroupQueryResult(ChartDataRequest request) {
        List<Map> mappedResults = this.getGroupQueryDataList(request);
        if (CollUtil.isEmpty(mappedResults)) {
            return new GroupQueryResult();
        }
        // 组装数据 给前端使用
        Map<String, List<Object>> groupAggsMap = new HashMap<>();
        for (Map mappedResult : mappedResults) {
            for (Object o : mappedResult.keySet()) {
                String key = o.toString();
                if (key.equals(MONGODB_ID)) {
                    continue;
                }
                if (!groupAggsMap.containsKey(key)) {
                    groupAggsMap.put(key, CollUtil.toList(mappedResult.get(key)));
                } else {
                    groupAggsMap.get(key).add(mappedResult.get(key));
                }
            }
        }
        List<String> groupList = mappedResults.stream().map(item -> {
            // 多个分组字段 会是一个map
            if (item.get(MONGODB_ID) instanceof Map) {
                return CollUtil.join(MapUtil.getQuietly(item, MONGODB_ID, new TypeReference<Map<String, Object>>() {
                }, null).values(), "-");
            } else {
                return MapUtil.getStr(item, MONGODB_ID);
            }
        }).collect(Collectors.toList());
        return new GroupQueryResult(groupList, groupAggsMap);
    }

}
